using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace PluginManager
{
    /// <summary>
    /// This class allows the user to recieve events that have been thrown
    /// by the core. Events in other plugins will be thrown from the core
    /// as well. Extending this class allows a plugin to hear events from
    /// any plugin without creating any references to anything.
    /// </summary>
    /// <remarks>
    /// The only thing you need to do to capture events is to create a
    /// public method with the same same as the event that you wish to capture
    /// in the format of on[eventname] without Event at the end if it has it,
    /// with the corrent EventArgs Defined by the event.
    /// </remarks>
    /// <example>
    /// To capture the onMessageRecievedEvent use the following code
    /// <code>
    /// public void onMessageRecievedEvent(object sender, MessageArgs e)
    /// {
    ///     System.Console.WriteLine("{0}: {1}",e.Sender,e.Message);
    /// }
    /// </code>
    /// </example>
    public abstract class CoreEventListener : IDisposable
    {
        /// <summary>
        /// Acts as a midway between <see cref="Core"/> and this
        /// CoreEventListener.
        /// </summary>
        /// <param name="sender">The person who sent the Event</param>
        /// <param name="Name">The name of the method</param>
        /// <param name="e">the EventArgs</param>
        /// <remarks>
        /// This uses Reflection to find the method named 
        /// <paramref name="Name"/> and then Converts the 
        /// <paramref name="e"/> into the Correct Type of EventArgs
        /// and "fires" the event.
        /// </remarks>
        public void onEvent(object sender, string Name, EventArgs e)
        {
            if (sender != null && sender.GetType() == this.GetType()) return;
            foreach (MethodInfo mi in this.GetType().GetMethods())
            {

                if (mi.Name == Name)
                {
                    ParameterInfo[] pis = mi.GetParameters();
                    mi.Invoke(this, new object[] { sender, Convert.ChangeType(e, e.GetType()) });
                }
            }
        }

        #region IDisposable Members
        /// <summary>
        /// Disposes the resources of the object
        /// </summary>
        public abstract void Dispose();

        #endregion
    }
}
